package android.os;

import android.VirtualAndroidUtils;
import io.reactivex.Scheduler;
import io.reactivex.Single;
import io.reactivex.SingleObserver;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * @author slc
 * @date 2022/03/29 下午 2:44
 */
public class Handler {
    private final Map<Integer, List<Disposable>> disposableMap = new ConcurrentHashMap<>();
    private final Scheduler scheduler;

    public Handler() {
        scheduler = VirtualAndroidUtils.javaFxScheduler;
    }

    public Handler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    public boolean sendMessage(Message message) {
        return sendMessageDelayed(message, 0);
    }

    public boolean sendEmptyMessageDelayed(int what, long delayed) {
        Message message = new Message();
        message.what = what;
        return sendMessageDelayed(message, delayed);
    }

    public boolean sendMessageDelayed(Message message, long delayed) {
        Single.just(message)
                .delay(delayed, TimeUnit.MILLISECONDS)
                .compose(upstream -> upstream.subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(scheduler))
                .subscribe(new SingleObserver<Message>() {
                    private Disposable disposable;
                    private final int what = message.what;

                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        this.disposable = d;
                        List<Disposable> disposableList = disposableMap.computeIfAbsent(this.what, k -> new ArrayList<>());
                        disposableList.add(d);
                    }

                    @Override
                    public void onSuccess(@NonNull Message message) {
                        removeDisposable();
                        handleMessage(message);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        removeDisposable();
                    }

                    private void removeDisposable() {
                        List<Disposable> disposableList = disposableMap.get(this.what);
                        if (disposableList != null) {
                            disposableList.remove(this.disposable);
                        }
                    }
                });
        return true;
    }

    public void removeMessages(int what) {
        synchronized (disposableMap) {
            List<Disposable> disposableList = disposableMap.get(what);
            if (disposableList != null && !disposableList.isEmpty()) {
                disposableList.forEach(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) {
                        if (!disposable.isDisposed()) {
                            disposable.dispose();
                        }
                    }
                });
            }
            disposableMap.remove(what);
        }
    }

    public void removeAllMessages() {
        this.disposableMap.keySet().forEach(this::removeMessages);
    }


    public void handleMessage(Message message) {

    }

}
